package com.common.security.interceptor;

import cn.hutool.core.util.StrUtil;
import com.common.core.constants.Constants;
import com.common.core.constants.HttpConstants;
import com.common.core.domain.R;
import com.common.core.enums.ResultCode;
import com.common.core.utils.ThreadLocalUtil;
import com.common.security.service.TokenService;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson2.JSON;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import java.io.IOException;
import java.io.PrintWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenService tokenService;

    @Value("${jwt.secret}")
    private String secret;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        try {
            String token = getToken(request);
            if (StrUtil.isEmpty(token)) {
                log.warn("请求缺少token: {}", request.getRequestURI());
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setCharacterEncoding("UTF-8");
                PrintWriter writer = response.getWriter();
                writer.write(JSON.toJSONString(R.failed(ResultCode.FAILED_UNAUTHORIZED)));
                writer.flush();
                return false;
            }

            Claims claims;
            try {
                claims = tokenService.getClaims(token, secret);
                if (claims == null) {
                    log.error("Token解析失败，claims为空: {}", token);
                    return handleAuthFailure(response, "令牌已过期或验证不正确");
                }
            } catch (Exception e) {
                log.error("Token解析异常: {}", token, e);
                return handleAuthFailure(response, "令牌已过期或验证不正确");
            }

            Long userId = tokenService.getUserId(claims);
            String userKey = tokenService.getUserKey(claims);
            
            if (userId == null || StrUtil.isEmpty(userKey)) {
                log.error("Token中用户信息不完整，userId: {}, userKey: {}", userId, userKey);
                return handleAuthFailure(response, "令牌验证失败");
            }

            ThreadLocalUtil.set(Constants.USER_ID, userId);
            ThreadLocalUtil.set(Constants.USER_KEY, userKey);
            
            try {
                tokenService.extendToken(claims);
            } catch (Exception e) {
                log.warn("延长token有效期失败: {}", userKey, e);
                // 延长token失败不影响本次请求，只记录日志
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("Token拦截器处理异常: {}", request.getRequestURI(), e);
            return handleAuthFailure(response, "系统异常，请稍后重试");
        }
    }

    private boolean handleAuthFailure(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        PrintWriter writer = response.getWriter();
        writer.write(JSON.toJSONString(R.failed(ResultCode.FAILED_UNAUTHORIZED.getCode(), message)));
        writer.flush();
        return false;
    }

    private String getToken(HttpServletRequest request) {
        String token = request.getHeader(HttpConstants.AUTHENTICATION);
        if(StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)){
            token = token.replace(HttpConstants.PREFIX,"");
        }
        return token;
    }
}
